package main

import "fmt"

//切片
func main() {
	var s1 []int    //定义一个存放int类型元素的切片
	var s2 []string //定义一个存放string类型元素的切片
	fmt.Printf("%T\t%T \n", s1, s2)
	fmt.Println(s1, s2)
	//切片是引用类型，不支持直接比较，只能和nil比较
	fmt.Println(s1 == nil)
	fmt.Println(s2 == nil)
	//初始化
	s1 = []int{1, 2, 3}
	s2 = []string{"沙河", "张江", "平山村"}
	fmt.Println(s1, s2)
	fmt.Println(s1 == nil)
	fmt.Println(s2 == nil)

	/* 	切片拥有自己的长度和容量，我们可以通过使用内置的len()函数求长度，
	   	使用内置的cap()函数求切片的容量。 */
	fmt.Printf("len(s1):%d\tcap(s1):%d \n", len(s1), cap(s1))
	fmt.Printf("len(s2):%d\tcap(s2):%d \n", len(s2), cap(s2))

	//2.由数组得到切片
	a1 := [...]int{1, 3, 5, 7, 9, 11, 13}
	//基于一个数字切割，左包含右不包含（左闭右开）
	s3 := a1[0:4] //左包含，右不包含   1 3,5,7
	fmt.Printf("%T\t%v \n", s3, s3)

	s4 := a1[1:6] //左包含，右不包含   3, 5, 7, 9, 11,
	fmt.Printf("%T\t%v \n", s4, s4)

	s5 := a1[:4] //从0开始   1, 3, 5, 7
	fmt.Printf("%T\t%v \n", s5, s5)

	s6 := a1[3:] //从3开始    7, 9, 11, 13
	fmt.Printf("%T\t%v \n", s6, s6)

	s7 := a1[:] //全部
	fmt.Printf("%T\t%v \n", s7, s7)
	/* 	1、切片指向一个底层的数组
	   	2、切片的长度就是它元素的个数
	   	3、切片的容量是底层数组从切片的第一个元素到最后一个元素的数量 */
	fmt.Printf("len(s3):%d\tcap(s3):%d \n", len(s3), cap(s3))
	fmt.Printf("len(s4):%d\tcap(s4):%d \n", len(s4), cap(s4))
	fmt.Printf("len(s5):%d\tcap(s5):%d \n", len(s5), cap(s5))
	fmt.Printf("len(s6):%d\tcap(s6):%d \n", len(s6), cap(s6))
	fmt.Printf("len(s7):%d\tcap(s7):%d \n", len(s7), cap(s7))

	//切片再切片
	s8 := s6[2:]
	fmt.Printf("s8:%d\tlen(s8):%d\tcap(s8):%d \n", s8, len(s8), cap(s8))

	//切片是引用类型，都指向了底层的一个数组
	fmt.Println(s6)
	a1[6] = 1300    //修改底层数组的值
	fmt.Println(s6) //引用传递性
	fmt.Println(s8) //引用传递性

	//索引的上限是cap(s)而不是len(s)
	s9 := s4[2:6]
	fmt.Printf("s9:%d\tlen(s9):%d\tcap(s9):%d \n", s9, len(s9), cap(s9))

	/*
	  要检查切片是否为空，请始终使用len(s) == 0来判断，
	  而不应该使用s == nil来判断。 */

}
